home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Diamond Collection / The Diamond Collection (Software Vault)(Digital Impact).ISO / cdr48 / 386p_200.zip / OPTIMIZE.TXT < prev    next >
Text File  |  1995-01-06  |  47KB  |  1,102 lines

  1. Ok! You read a good manual about assembly programming, coded your stuff
  2. and got the same benchmarks on a thing written in C/C++, what can you do?
  3. You start reading a manual about "generic" optimizations
  4. and then your second code release runs head to head against C code, but
  5. you still didn't beat the code wizards, so what to do ?
  6. Keep reading this ....
  7.  
  8. Some useful informations about how to optimize code on a 386/486/Pentium
  9.  
  10. This initially was a posting on the Internet made by
  11.  
  12.         Michael Kunstelj.
  13.         Contact at :  virteam@smoke.canberra.edu.au
  14.                         or
  15.                       mick@cairo.anu.edu.au
  16.  
  17. Initially it included 486 and Pentium optimizations with some "holes"
  18. (like the profiling instructions), i filled the Pentium "holes"
  19. then refined some exaplanations (uh! maybe i made 'em worse! :} ).
  20. Then added some not-so-obviuos cache optimization techniques
  21. and other infos about specific optimizations you can make on 386.
  22.  
  23.         Lorenzo Micheletto
  24. N.B.
  25.         I added some generic examples about how a cpu works
  26.         BUT they are just examples, intel cpus work in slightly different ways.
  27.  
  28. N.B./2
  29.         Always check in the books for things you are not sure
  30.         there may be typos here.
  31.  
  32. ----------------------------------
  33. Brief intro about how a CPU works
  34. ----------------------------------
  35.  
  36. Now a brief intro on the innards Intel CPUs.
  37.  
  38. Most processors these days have within in them a system termed a "pipeline".
  39. The 486 / 586 are certainly within this category.  However, most people 
  40. aren't quite sure what exactly a pipeline is, here follows a complete
  41. explanation:
  42.  
  43. The execution of a machine code instruction can be roughtly split
  44. in five stages:   [n.b. this is a generic pipeline]
  45.         1) FETCH instruction opcode and immediate data
  46.         2) DECODE opcode and align immediata data into temporary registers
  47.         3) CALCULATE ADDRESS OF OPERANDS and load 'em into memory.
  48.            (calculate the address of memory locations to access
  49.             and select the register operands to use)
  50.            (sometimes called DECODE 2)
  51.         4) EXECUTE instruction (loading memory operands if needed)
  52.            & write results to INTERNAL registers
  53.         5) WRITEBACK memory-operand results to memory
  54.  
  55. Every stage takes ONE OR MORE cpu cycles to be completed, but usually
  56. a modern cpu needs just one cpu cycle for every execution stage
  57. (excluding stages 1 and 5 that have to deal with memory/cache access
  58.  and stage 4 when "complex" microcoded instructions are executed).
  59.  
  60. A cpu-core ( the "real" cpu, not cache support nor the other things
  61. that are usually integrated into a modern cpu) has five "specialized"
  62. units, one for every stage of instruction execution, plus a "register file"
  63. (and ultra-fast on-chip memory where internal register values
  64.  are stored) and a CONTROL UNIT.
  65.  
  66. The control unit "coordinates" the action of all the other units
  67. so they can work together.
  68.  
  69. Here follows an extended ascii drawing
  70. of ONE on the many ways these units can be connected
  71. (use a ms-dos text editor to see this, or convert it to the
  72.  Windows line-drawing character set if you are using a Windows editor):
  73.  
  74.               MEMORY INPUT ("memory load" unit)
  75.                         │                                ┌────────────┐
  76.                         └─────┬─>┌────────────┐<────────>│            │
  77.                              ┌┼┐ │ FETCH      │          │            │
  78.        ┌─────────────────────┘│└>└────────────┴──┐       │            │
  79.        │ (instruction pointer)│                  │       │            │
  80.        │                      │  ┌────────────┐<─┘       │            │
  81.        │                      │  │ DECODE     │<────────>│            │
  82.        │                      │  └────────────┴──┐       │            │
  83.        │                      │                  │       │            │
  84.        │                      │  ┌────────────┐<─┘       │ CONTROL    │
  85.        │                     ┌┘  │ ADDRESS C. │<────────>│            │
  86.        │                ┌────┼──>└────────────┴──┐       │ UNIT       │
  87.        │                │    └┐                  │       │            │
  88.  ┌─────┴────────────────┴─┐   └─>┌────────────┐<─┘       │            │
  89.  │ REGISTER FILE          ├─────>│ EXECUTE    │<────────>│            │
  90.  └────────────────────────┘<─────┴────────────┴──┐       │            │
  91.                                                  │       │            │
  92.                                  ┌────────────┐<─┘       │            │
  93.                                  │ WRITEBACK  │<────────>│            │
  94.                                  └────────────┴──┐       │            │
  95.                                                  │       └────────────┘
  96.                                MEMORY OUTPUT <───┘
  97.                               ("memory store" unit)
  98.  
  99. If you look the drawing, the control unit needs to communicate
  100. with all the other units to make 'em work together.
  101. Usually the "control unit" is scattered in little units that coordinates
  102. intruction and data flow between adiacent units, but you can think
  103. at it as a single indipendent unit.
  104.  
  105. The five execution units are what gives the "raw" cpu power
  106. but the control unit is what lets you fully utilize 'em.
  107.  
  108. Let's suppose every unit performs one operation in one step.
  109.  
  110. With a "cheap" control unit, to execute a complete machine language
  111. instruction you first enable  FETCH, then you enable DECODE
  112. and so on until WRITEBACK is completed and the control unit
  113. enables FETCH again to execute the next instruction.
  114.  
  115. This is what happens into an "absolutely not pipelined" cpu
  116. with "one cycle" stages, the fastest instructions takes 5 cycles
  117. but the control unit is very simple
  118. (just a circular shift register that enables one unit at a time).
  119.  
  120. Of course this is the worst case, nobody is so jerk to build
  121. a cpu like that.
  122.  
  123. Every cpu stage-execution unit is a stand alone thing, it has its hardware
  124. and its "temporary registers" so it is capable to operate "alone".
  125.  
  126. So, IF THE CONTROL UNIT can SINCHRONIZE the operations
  127. of all the stage-execution units, it can make 'em WORK IN PIPELINE
  128. (like in a factory, where every worker/robot in a production line
  129.  a) receives a partially refined product from the previous worker in line
  130.  b) performs some simple operations to refine the product a little more
  131.  c) pass the result to the next worker in line
  132. ).
  133. A cpu with such a control unit is called a pipelined CPU.
  134.  
  135. If you have to execute in sequence instructions A,B,C,D,E
  136. on a pipelined processor ....
  137.  
  138. While the WRITEBACK unit is performing stage 5 of A
  139. the EXECUTION         unit can perform stage 4 of B
  140. the ADDRESS CALCULATE unit can perform stage 3 of C
  141. the DECODE            unit can perform stage 2 of D
  142. and the FETCH         unit can perform stage 1 of E
  143.  
  144. So if you start the cpu at instruction A
  145. it looks like that instruction A takes 5 cycles
  146. while instructions B,C,D,E (immediately one stage behind) looks like they take
  147. JUST ONE CYCLE!!!
  148.  
  149. So if you execute a SEQUENCE of 8 instructions
  150. on a "not pipelined" processor with a five stage "pipe"
  151. it takes 40 steps to execute the sequence
  152. while on a pipelined processor this takes 5+7=12  steps!!!
  153. ( 5 steps for the first instruction to get thru the pipeline
  154.  then 7 steps for the other instructions immediately "one step" behind)
  155. And the more instructions are executed in sequence, the more it looks like
  156. every instruction takes "just" one cycle to execute.
  157.  
  158.  
  159. This is of course the optimal situation, when the processor pipeline
  160. is filled and WHEN EVERY INSTRUCTION DOES NOT USE MEMORY/REGISTER OPERANDS
  161. "still under processing" IN SUCCESSIVE EXECUTION-STAGES!!!!!!
  162.  
  163. -------------------------------------------------------------------------------
  164. THINGS A CPU MUST CHECK TO MAKE A PIPELINE WORK CORRECTLY
  165.  
  166. A pipelined processor control-unit must "check" :
  167.  A) at stage 1 (FETCH)
  168.     IF in stage 2..4 there are JUMP instructions
  169.              [ they change the program counter
  170.                (the same register used by the fetch unit)
  171.              ]
  172.     THEN stage 1 must "wait" until the jump is completed
  173.          and then "restarts", loading  the memory location pointed by the
  174.          new program counter value.
  175.  
  176.     Because the jump opcode must pass thru the decode stage ...
  177.     ... if the DECODE unit "detects" a jump opcode, it makes the FETCH unit
  178.     "stops" AT LEAST for two cycles until the jump is performed.
  179.     This of course means the processor pipeline "wastes" some cpu cycles.
  180.  
  181.     A 486 handles jumps in a smarter way, when the FETCH unit loads
  182.     a jump instruction, it goes on assuming the jump WON'T BE TAKEN
  183.     (it read the instructions following the jump).
  184.     If the jump is taken, the values in the DECODE 1 and DECODE 2 units
  185.     are "discarded" and the FETCH unit starts loading from the new
  186.     program counter value.
  187.     This explains why on 486 relative jumps (the fastest jumps) takes
  188.     3 cycles if taken    (two cycles "lost")
  189.     1 cycle if not taken (no cycles lost)
  190.  
  191.     A "smarter" control unit can recognize in advance unconditional jumps
  192.     and start immediately loading opcodes from the new program counter
  193.     location
  194.     AND/OR try to "predict" the jump destination of conditional jumps
  195.     (like the Pentium does).
  196.  
  197.  
  198.  B) at step 3  (ADDRESS CALCULATION)
  199.     IF in stage 3 a register needed for address calculation is under processing
  200.        in stage 4 (EXECUTE)
  201.     THEN the stage 3 unit generates a "do nothing" control sequence
  202.          for one cpu cycle.
  203.  
  204.  C) memory access conflicts
  205.     These can be caused by lots of different things, they are usually
  206.     resolved by the memory load/store units.
  207.  
  208. Told in a short way, in a fully pipelined processor
  209. when the pipeline is "working on a sequence"
  210. the first instruction in the sequence takes the full execution time
  211. while the other instructions takes a shorter time (usually one cycle)
  212. because they are immediately behind, this means they "look faster"
  213. (and in fact they are, because the pipeline fully utilizes all the functional
  214. units it has).
  215.  
  216. If some instructions "modify" values needed in the previous cpu stages
  217. the control unit stops the unit needing those values (and the others behind it)
  218. and inserts "do nothing" codes into the successive units in the processor pipe
  219. to make things work as expected (this is called a PIPELINE STALL
  220. or a PIPELINE FLUSH)
  221.  
  222. This explains why usually a taken jump takes more time than one that's not taken
  223. (when a jump is performed you must flush the pipeline).
  224.  
  225. The newer processors includes JUMP PREDICTION UNITS that handles
  226. jump faster, but the less you jump, the better.
  227.  
  228. ------------------------------------------------------------------------------
  229. PIPELINING IN INTEL PROCESSORS:
  230.  
  231. The 386 is a "partially pipelined" processor with some optimizations.
  232. It checks for jumps ( A check) in a quite slow way
  233. and most of times can execute every stage in one cycle.
  234. It cannot perform the address generation check (B check)
  235. so it must execute stage 3 and 4 in "not pipelined mode".
  236. This explains why THE FASTEST 386 INSTRUCTIONS TAKE TWO CYCLES
  237. ( stage 3 unit must wait stage 4 to complete before managing
  238.   the next instructions).
  239.  
  240. The 486 has an improved EXECUTION unit (stage 4), improved memory access
  241. AND its control unit can perform the address generation check
  242. so that it can pipe stage 3 and 4 if there are no
  243. register/memory conflicts with two successive instructions.
  244. This explains why lots of 486 instructions take just one cycle
  245. (if the pipeline is filled and no pipeline stalls are produced).
  246. What's more, pipeline reloading is improved, so even jumps have less
  247. impact on execution time.
  248. It also has a 4Kbyte internal cache that boosts memory access
  249. and allows big gains from strip-mining optimizations.
  250. Another nice thing is the BURST READ access that accelerates memory reads
  251. when it needs to update its internal cache.
  252.  
  253. PIPELINED,SUPERSCALAR & BRANCH PREDITING CPU: THE PENTIUM
  254.  
  255. Well, what's beyound a fully pipelined processor like the 486 ?
  256. There is a 586/Pentium processor, that's SUPER SCALAR (more than one pipeline)
  257. and BRANCH PREDICTING (it has a specialized unit that annotates the
  258. position and the result of some og the most recent  jumps, and so
  259. it can try to "guess" from where the next instruction after the jump execution
  260. will be loaded, if it guess correcly a pipeline stall is avoided, else
  261. it stalls)(this helps speeding up the execution of nested loops).
  262.  
  263. The 586 can execute UP TO TWO integer operations in a single step
  264. (because it has TWO pipelines, but with some limitations)
  265. it can BURST READ/WRITE and has TWO indipendent 8k caches
  266. (Harvard style CPU to cache architecture) this means you can
  267. strip-mine to the max. if strips fit into the 8Kbyte data cache.
  268.  
  269. Well, now you know how they work, let's see how to make 'em work to the max.
  270.  
  271. ------------------------------------------------------------------------------
  272. SPEEDING UP 486/586 CODE.
  273. ------------------------------------------------------------------------------
  274.  
  275. -------------------------------
  276. ADDRESS GENERATION STALLS (AGI)
  277. -------------------------------
  278. An Address Generation Interlock occurs when a register which is
  279. currently being used as the base or an index was the destination component 
  280. of a previous instruction (the stage 3 to 4 pipeline stall i described above)
  281.  
  282. For example,:
  283.  
  284.         add edx, 4
  285.         // AGI, ONE CLOCK STALL
  286.         mov esi, [edx]
  287.  
  288. For the 486, AGI's can only occur on adjacent instructions.
  289.  
  290. On the 586 or Pentium instructions up to 3 locations away can cause an AGI.
  291. ( i.e. an instruction waiting to execute step 4 on pipeline 1
  292.        may need to wait the result produced by an instruction
  293.        still executing on pipeline 2)
  294.  
  295.                 pipeline step              pipe1  pipe2
  296.         addres_calculate/fetch_operand       C      D    |
  297.         execute                              B      A    |
  298.                                                          V
  299.  
  300.       If C needs the results of A, it must stall pipeline 1 for one cycle
  301.       to wait for A to "exit from" pipeline 2.
  302.       If C needs the results of D, it must stall pipeline 1 for two cycles
  303.       to wait for D to "exit from" pipeline 2.
  304.  
  305. An example of 3 instruction away AGI:
  306.  
  307.         add esi, 4
  308.         pop ebx
  309.         dec ebx
  310.         mov edx, [esi]
  311.  
  312. Takes 4 clocks on a 486.  On a 586, the move command must wait for the 
  313. add command, thus AGI stalling for one clock.  The code above then 
  314. would run in three clock cycles on a 586.
  315.  
  316. Remember that even instructions that read or write implicitly to registers
  317. cause AGI stalls:
  318.  
  319.     mov esp,ebp
  320.     pop ebp.
  321.  
  322.     is executed as...
  323.  
  324.     mov esp,ebp
  325.     [agi]          ; pop uses the esp as a pointer
  326.     pop ebp
  327.  
  328. ----------------------------
  329. INSTRUCTION DECODING STALLS:
  330. ----------------------------
  331.  
  332. When decoding an instruction with an IMMEDIATE VALUE
  333. AND
  334. either an  INDEX OFFSET or an IMMEDIATE DISPLACEMENT
  335. 486's have a one clock penalty. (586's do not)
  336.  
  337.         Example:
  338.  
  339.                 mov  spam, 248
  340.                 mov dword ptr [esp+4], 1
  341.  
  342. This happens because the decode stage of the pipeline can read and decode
  343. ONE "immediate" value at a time
  344. while an immediate value and an immediate offset are TWO immediate values.
  345. The 586 instead has not such problems (when decoding) (execution is different)
  346.  
  347. ---------------------------------
  348. REGISTER ACCESS CPU STALLS:
  349. ---------------------------------
  350.  
  351. 486's have a 1 clock penalty when modifying the lower word of a DWORD register
  352. that's used immediately after it, 586's do not.
  353.         Example:
  354.                 mov al,0
  355.                 mov [ebp], eax
  356.                 (a one clock penalty on 486, no penalty on a 586)
  357.  
  358.  
  359. -------------------------------
  360. CODE ALIGNMENT
  361. -------------------------------
  362.  
  363. To speed up the instructions, alignment of code should be on the
  364. beginning of cache boundaries.
  365. (32 bytes on 586, 16 bytes on 486)
  366.  
  367. Thus, start your routine on the start of the cache page.
  368. This way, when someone calls the routine, the processor
  369. will just have to load a cache line to get the first sequence to feed
  370. into the pipeline, and while they are executing it will have
  371. enough time to load the other cache lines needed.
  372.  
  373. This will speed up the processing  of all the instructions within that page.
  374. The effect of this speed up on the 586 is not a dramatic as is it is on the 486
  375. because the 586 has bigger caches and faster access to memory
  376. so a cache line load/store has less impact on cpu.
  377.  
  378. ------------------------------
  379. DATA ALIGNMENT
  380. ------------------------------
  381.  
  382. Misaligned access in the data cache causes an extra 3 cycles on both the 
  383. 486 and 586.
  384.  
  385. Ways to speed up data:
  386. For DWORD data, alignment should be on a 4-byte boundary.
  387. For WORD data, alignment should be on a 2 byte boundary for the 486, 
  388. and simply within the 4-byte page for the 586.
  389. For 8 byte data (64 bits), data should be aligned on a 8-byte boundary
  390. so it is possible to use BURST READS (and burst writes too, on a Pentium).
  391.  
  392. And yes, on many applications with tight inner loops, these things do 
  393. accumulate to make a noticeable speed-up.
  394.  
  395. -------------------------------------------------------------------------------
  396. SPEEDING UP REGISTER AND OPERAND USAGE
  397. -------------------------------------------------------------------------------
  398.  
  399. Use the EAX as much as possible.
  400. Many instructions are 1 byte shorter when using EAX.
  401. That's less code you have to move around and slightly less internal processing.
  402. Use the DS register as much as possible for roughly the same reason,
  403. In the case of several references being made to a variable addressed with a 
  404. displacement, load the displacement into a register.
  405.  
  406. Try to use the ESP register to reference the stack in lower levels of your 
  407. subroutines (faster than push/pop things and leaves EBP free for other
  408. uses)
  409.  
  410.  
  411. -------------------------------------------------------------------------------
  412. HANDY INFO ON SPEEDING UP INTEGER INSTRUCTIONS
  413. -------------------------------------------------------------------------------
  414.  
  415. 1. Avoid using complex instructions like LEAVE, ENTER, LOOP, string 
  416.    instructions etc  Simpler instructions will get the job done faster.
  417.    Simpler instructions have been getting faster with every new processor
  418.    that has come along.
  419.  
  420. 2. With 8-bit operands, do your best to use the byte opcodes, rather than 
  421.    using the 32 bit instructions  with sign and zero extended modes.
  422.    Internal sign extension is expensive, and speed increases can be found by
  423.    simplifying the process as much as possible.
  424.  
  425. 3.  LEA's generally increase the chance of AGI's.  However, LEA's can be
  426.     advantageous because:
  427.     *  In many cases an LEA instruction may be used to replace constant
  428.        multiply instructions. (a sequence of LEA, add and shift for example)
  429.     *  LEA may be used as a three/four operand addition instruction.
  430.        LEA ECX, [EAX+EBX*4+ARRAY_NAME]
  431.     *  Can be advantageous to avoid copying a register when both operands to
  432.        an ADD are being used after the ADD as LEA need not overwrite its
  433.        operands.
  434.  
  435.     The general rule is that the "generic"
  436.  
  437.     LEA A,[B+C*INDEX+DISPLACEMENT]
  438.  
  439.         where A can be a register or a memory location and B,C are registers
  440.         and INDEX=1,2,4,8
  441.         and DISPLACEMENT = 0 ... 4*1024*1024*1024
  442.                            or (if performing signed int operations)
  443.                            -2*1024*1024*1024 ... + (2*1024*1024*1024 -1 )
  444.  
  445.     replaces the "generic" worst-case sequence
  446.  
  447.     MOV X,C    ; X is a "dummy" register
  448.     MOV A,B
  449.     MUL X,INDEX    ;actually  SHL X, (log2(INDEX))
  450.     ADD A,DISPLACEMENT
  451.     ADD A,X
  452.  
  453.     So using LEA you can actually "pack"  up to FIVE instructions into one
  454.     Even counting a "worst case" of TWO OR THREE AGIs caused by the LEA
  455.     this is very fast compared to "normal" code.
  456.     What's more, cpu registers are precious, and using LEA
  457.     you don't need a dummy "X" register to preserve the value of B and C.
  458.  
  459. 4. Zero-Extension with short ints terror tales
  460.  
  461.   The MOVZX  takes four cycles to execute due to due zero-extension
  462.   wobblies. A better way to load a byte into a register is by:
  463.      xor eax,eax
  464.      mov al,memory
  465.  
  466.   As the xor just clears the top parts of EAX, the xor may be placed on the
  467.   OUTSIDE of a loop that uses just byte values.
  468.   The 586 shows greater response to such actions.
  469.  
  470.   It is recommended that 16 bit data be accessed with the MOVSX and
  471.   MOVZX if you cannot place the XOR on the outside of the loop.
  472.  
  473.   N.B. Do the "replacement" only for movsx/zx inside loops.
  474.  
  475. 5. When comparing a value in a register with 0, use the TEST command.
  476.   
  477.   TEST operands by ANDing the operands together without spending any
  478.   internal time worrying about a destination register.
  479.   Use test when comparing the result of a boolean AND command with an
  480.   immediate constant for equality or inequality if the register is EAX.
  481.   You can also use it for zero testing.
  482.   (i.e. test ebx,ebx  sets the zero flag if ebx is zero)
  483.  
  484. 6. Address Calculations
  485.  
  486.   Pull address calculations into load and store instructions.  Memory
  487.   reference instructions have 4 operands: a relocatable time segment base, a
  488.   base register, a scaled index register and a displacement.  Often several
  489.   integer instructions can be eliminated by fully using the operands of
  490.   memory addresses.  (more on this later)
  491.  
  492. 7.  INTEGER DIVIDE
  493.   In most cases, an Integer Divide is preceded by a CDQ instruction.
  494.   This is as  divide instructions use EDX:EAX as  the dividend and CDQ sets
  495.   up EDX.
  496.   It is better to copy EAX into EDX, then arithmetic-right-shift EDX 31 places
  497.   to sign extend.
  498.   The copy/shift instructions take the same number of clocks as CDQ,
  499.   however, on 586's allows two other instructions to execute at the same
  500.   time.  If you know the value is a positive, use XOR EDX,EDX.
  501.  
  502. 8. INTEGER MULTIPLY
  503.   The integer multiply by an immediate can usually be replaced with a faster
  504.   and simpler series of shifts, subs, adds and lea's.
  505.   As a rule of thumb when 6 or fewer bits are set in the binary representation
  506.   of the constant, it is better to look at other ways of multiplying and not use
  507.   INTEGER MULTIPLY. (the thumb value is 8 on a 586)
  508.   A simple way to do it is to shift and add for each bit set, or use LEA.
  509.  
  510.   Here the LEA instruction comes in as major cpu booster, for example:
  511.       LEA ECX,[EDX*2]       ; multiply EDX by 2 and store result into ECX
  512.       LEA ECX,[EDX+EDX*2]   ; multiply EDX by 3 and store result into ECX
  513.       LEA ECX,[EDX*4]       ; multiply EDX by 4 and store result into ECX
  514.       LEA ECX,[EDX+EDX*4]   ; multiply EDX by 5 and store result into ECX
  515.       LEA ECX,[EDX*8]       ; multiply EDX by 8 and store result into ECX
  516.       LEA ECX,[EDX+EDX*9]   ; multiply EDX by 9 and store result into ECX
  517.  
  518.   And you can combine leas too!!!!
  519.       lea ecx,[edx+edx*2]   ;
  520.       lea ecx,[ecx+ecx*8]   ;  ecx <--  edx*27
  521.   (of course, if you can, put three instructions between the two LEA
  522.    so even on Pentiums, no AGIs will be produced).
  523.  
  524. 9. Clearing Registers
  525.   Using   XOR reg,reg is fast but sets up conditions codes.
  526.   A slightly slower way to do it of course is to mov reg,0
  527.   which preserves condition codes.
  528.  
  529. 10. Avoid ENTER, instead, try something like:
  530.   PUSH EBP
  531.   mov ebp, esp
  532.   sub esp, BYTE_COUNT
  533.  
  534. 11. JUMP INSTRUCTIONS
  535.   Jump instruction come in two forms, one real near that jumps between -127
  536.   and 128 of the current location, and a 32 bit version that does a full jump.
  537.   The short form is quite a bit faster, however unfortunately many compilers
  538.   put long jumps where short jumps would suffice.
  539.   To ensure that short jumps can be used (when you know it is possible),
  540.   explicitly specify the destination as being byte length
  541.   (i.e use jmp short instead of plain jmp, if you can)
  542.  
  543. 12. Task Switching
  544.   Task Switching is evil.  It is slow,  real slow.  Avoid task switching too
  545.   often, as more and more of your time will be spent in processing the task
  546.   switch.
  547.   For faster task switching, perform you task switching in software.  This
  548.   allows a smaller processor state to be saved and restored.  Anything that
  549.   shaves time off  75+ clock cycles isn't all that bad in my book.
  550.  
  551. 13.  Minimize segment register loads and the use of far pointers as dearly
  552.   much as you can.  If you are doing a lot of processing on a small piece of
  553.   data far away, it might be faster just to copy the data to nearby and work
  554.   on it there (by the way, this is a good reason to use flat protected mode).
  555.  
  556. ...and....
  557.  
  558. 14. THINK ABOUT WHAT YOU WANT TO DO
  559.   All the other optimisations of Unrolling Loops, moving the invariant data
  560.   etc still apply.  That, however, is more an algorithmic problem for you, but
  561.   still keep it firmly in mind.
  562.  
  563. _______________________________________________________________________________
  564. 586 Specific Optimizations
  565. -------------------------------------------------------------------------------
  566.  
  567. The 586Pent has a five stage pipeline structure.
  568. However, the pipeline is split into two different pipelines, known 
  569. as Pipeline U and Pipeline V.   This allows two instructions to be
  570. executed in parallel and thus presents the opportunity of 
  571. executing two/instuctions per clock.
  572. The U pipeline is very much like the 486 pipeline, in that it can handle
  573. the entire set of instructions.  Pipeline V on the other hand can
  574. handle only "simple" instructions.
  575. The fast parts of the U and V pipelines are possible as much of the 
  576. functions are hardwired not microcoded.
  577.  
  578. Anyway, I've blurted on about that for a bit, but what you want to know
  579. is "How to I get two instructions running in one clock/cycle?"
  580.  
  581. Lament no further, here are the criteria:
  582.  
  583.   1. Both instructions must be simple (see below)
  584.   2. There must not be a read-after-write or write-after-read
  585.       register/flag dependencies between them.
  586.   3. Neither can have a displacement and an immediate
  587.   4. Instructions with prefixes can only occurr in the U-pipe
  588.      (except for branches on condition jz,jc, etc.etc.)
  589.  
  590. The following are considered "simple" instructions,
  591. the ALU means any ALU command (ADD etc):
  592.  
  593.  1. Mov reg, reg/mem/immed
  594.  2. mov mem, reg/imm
  595.  3. ALU reg, reg/mem/immed
  596.  4. ALU mem, reg/immed
  597.  5. inc reg/mem
  598.  6. dec reg/mem
  599.  7. push reg/mem
  600.  8. pop reg
  601.  9. nop
  602.  10. lea reg/mem
  603.  11. Jmp/ Call / Jcc near
  604.  
  605. N.B Remember only the U pipe can perform SHIFTS/ROTATIONS
  606.     so "couple" every shift/rol with a simple instruction
  607.     before and after to be sure every pipeline is filled.
  608.  
  609. Note, however, than while both pipelines can perform ALU
  610. instructions concurrently, this is not the case when
  611. one ALU instruction requires the output of the
  612. other pipeline ALU instruction.
  613. Example:  ALU instruction in pipe U and
  614.           performing ADC in pipe V.
  615.  
  616. There are two exceptions to this rule:
  617. 1) In the case of a compare/branch combination.
  618. 2) With push/pop combinations (because of optimized stack access)
  619.  
  620. --------------------------
  621. Branch Prediction
  622. -------------------------
  623.  
  624. Another nice optimisation with the 586 hardware is that whenever there is 
  625. a possibility of a jump, for example, Jg, the 586 can automatically
  626. start "reading ahead" code from the jump location just in case the the
  627. Jump is accepted.  Remember the CODE alignment thing above?  Well,
  628. it couldn't hurt your grandmother to align the labels on the code pages.
  629.  
  630. ------------------------------------------
  631. Amazing new 586 Optimizations and speedups
  632. ------------------------------------------
  633.  
  634. The 586 has a lot of really nice optimizations and kick-ass
  635. features in addition to what I've mentioned above, unfortunately,
  636. this information is proprietary and will only be given
  637. to people who sign non-disclosure agreements and shell out a
  638.  $$ or two...  Bummer...
  639. (Meethinks, 586 clone-makers won't be too happy about that... :-) )
  640. Compiler/OS makers will probably be the purchasers.
  641. Quite a few of these optimisations won't work on anything less than
  642. a 586, so don't sweat too much about it.  Hey, just write
  643. for 386/486/586 and you'll be ok.
  644.  
  645. Hovewer, i found a nice article on July 1994 Byte about some
  646. "secret weapons of Pentium coders"....
  647.  
  648. ============================================================================
  649. PENTIUM'S PROFILING REGISTERS:
  650.  
  651. Pentiums have a set of 64bit "machine specific registers" (MSR)
  652. that are accessed by way of the RDMSR (read MSR) and WRMSR (write MSR)
  653. instructions.
  654.  
  655. THESE ARE PROTECTED MODE, RING 0 INSTRUCTIONS (CPU LEVEL 0)
  656. ( can work in a 386Powered programs only if executing under VCPI
  657.   XMS or "no V86 manager"
  658.   or if you find a way to "toggle" DPMI from ring 3 to ring 0)
  659. (I think they can work even if you boot ms-dos in real mode
  660.  and use the proper instruction prefixes needed to execute
  661.  32bit instructions in real mode).
  662.  
  663. -----------------------------------------------------------
  664. RDMSR   Read MSR
  665.         Copies the MSR register indexed by ECX
  666.         into the 64bit pair  EDX:EAX
  667.  
  668.         RDMSR macro
  669.                 db 0Fh,032h
  670.         endm
  671. -----------------------------------------------------------
  672. WRMSR   Write MSR
  673.         Copies into the MSR register indexed by ECX
  674.         the value contained into the 64bit pair  EDX:EAX
  675.  
  676.         Macro to insert it into code if your assembler
  677.         does not support Pentiums:
  678.  
  679.         WRMSR macro
  680.                 db 0Fh,030h
  681.         endm
  682. -----------------------------------------------------------
  683.  
  684.  
  685. Intel Pentium user manuals, documents only MSR 0, 1 and 0Eh
  686. and states that MSR 3, 0Fh and above 13h are reserved and illegal.
  687.  
  688. So, what's left? And what's useful to you ?
  689.  
  690. MSR 10h is the counter of CPU CYCLES since last power-up.
  691. That value can also be read with the RDTSC (Read time stamp counter)
  692. instruction)
  693. RDTSC is 0Fh,031h in bytes and must be executed while in ring 0 too.
  694.  
  695. MSR 10h is the most precise timer available on the Pentium
  696. because it "ticks" at the CPU frequency.
  697.  
  698. Then comes MSR 11h,12h and 13h there you will find the hot stuff
  699.  
  700. The lower 32bits of MSR 11h are actually two INDEXES
  701. INTO THE CPU PROFILING REGISTERS!!!!
  702.  
  703. The profiling registers are CPU EVENT TIMERS AND COUNTERS
  704. they can keep track of what's going on inside and outside
  705. your super-duper processor, they can detect nearly everything the CPU does.
  706.  
  707. The first 16bits of MSR11h selects
  708. the profiling register accessible thru MSR 12h.
  709. The second 16bits of MSR11h selects
  710. the profiling register accessible thru MSR 13h.
  711.  
  712. Here comes the format of the "profiling register indexes":
  713. bit 0..5 : type of the profiling register to access
  714. bit    6 : Set if you want to monitor the events in cpu ring 0,1,2 (system)
  715. bit    7 : Set if you want to monitor the events in cpu ring 3 (user level)
  716. bit    8 : 0 = access count-of-hardware-events
  717.            1 = access count-of-total-cpu-cycles used to process the cumulated
  718.                events.
  719.            (i'm not sure of this, maybe 0 means count time and 1 count events)
  720. bit 9..15: UNKNOWN, DO NOT MODIFY
  721.  
  722.  
  723.  
  724. Profiling registers types:
  725. INDEX  NAME
  726. 0       data write
  727. 1       data read
  728. 2       data TLB miss (translation look-aside buffer)
  729. 3       data read miss
  730. 4       data write miss
  731. 5       write (hit) to M or E state lines
  732. 6       data cache lines written back
  733. 7       data cache snoops
  734. 8       data cache snoop hits
  735. 9       memory accesses in both pipes
  736. 0Ah     bank conflict
  737. 0Bh     misaligned data memory reference
  738. 0Ch     code read
  739. 0Dh     code TLB miss
  740. 0Eh     code cache miss
  741. 0Fh     segment load
  742. 10h     ????
  743. 11h     ????
  744. 12h     branches
  745. 13h     BTB hits  (Branch Target Buffer)
  746. 14h     taken branch OR BTB hit
  747. 15h     pipeline flushes
  748. 16h     instructions executed
  749. 17h     instructions executed in V-pipe
  750. 18h     bus utilization (clocks)
  751. 19h     pipeline stalled by write backup
  752. 1Ah     pipeline stalled by data memory write
  753. 1Bh     pipeline stalled by write to E or M line
  754. 1Ch     locked bus cycles
  755. 1Dh     i/o read or write cycles
  756. 1Eh     non cacheable memory references
  757. 1Fh     AGI (Address Generation Interlock)
  758. 20h     ????
  759. 21h     ????
  760. 22h     FPU operations
  761. 23h     breakpoint 0 match
  762. 24h     breakpoint 1 match
  763. 25h     breakpoint 2 match
  764. 26h     breakpoint 3 match
  765. 27h     hardware interrupts
  766. 28h     data read or data write
  767. 29h     data read miss or data write miss
  768.  
  769. So if you want to profile things:
  770. 0) Set properly the environment of the test
  771.    (cache empty, cache filled with all the routine code, etc. etc.)
  772. 1) Set MSR 11h to the two counters you want to read
  773. 2) Read MSR 12h,13h to get the initial values,
  774. 3) Execute the code you want to profile
  775. 4) Read the final values of MSR 12h,13h
  776.    (without setting MSR 11h again this time).
  777. 5) Calculate the difference between the initial and final values.
  778.  
  779. This way if you are not sure how to optimize things
  780. you can actually test how they work and what's going on.
  781.  
  782. USING THE PROFILING REGISTER YOU CAN "TEST ON THE ROAD"
  783. YOUR CODE DOWN TO THE LAST CPU CYCLE!!!!!
  784.  
  785. -------------------------------------------------------------------------------
  786. 386 Optimization
  787. -------------------------------------------------------------------------------
  788.  
  789. Well, nobody buys a 386 now, right?
  790. But still lots of people has one....
  791. So if you wanna be 386 friendly remember .....
  792.  
  793.  
  794. --------------------------
  795. DECODE-AFTER-JUMP OVERHEAD
  796. --------------------------
  797.  
  798. When a jump is performed, a 386 spends some extra time decoding
  799. the next instruction to execute and flushing the pipeline.
  800.  
  801. THE FIRST INSTRUCTION requires exactly ONE EXTRA CPU CYCLE
  802. for every COMPONENT ( prefixes, opcode, mod/rm , sib ,offset, immediate value )
  803. of the instruction.  Notice i said COMPONENT!!!
  804. An 8bit displacement or a 32bit one, count always as an 1 extra cycle.
  805.  
  806. So, in 32bit mode (where no prefixes are needed for 32bit instructions):
  807.  
  808.         loopme: inc esi              ; opcode
  809.                 mov [edi+1234h],eax  ; opcode, mod/rm , immediate offset
  810.                 dec ecx              ; opcode
  811.                 jne short loopme     ; opcode short_displacement
  812.  
  813. IS FASTER THAN:
  814.  
  815.         loopme: mov [edi+1234h],eax
  816.                 inc esi
  817.                 dec ecx
  818.                 jne short loopme
  819.  
  820. Because placing first the three component mov instruction
  821. adds 2 cycles to the instruction execution time, weird, uh?
  822. But if you remember this thing, you can boost 386 code a lot.
  823.  
  824. By the way, remember that "pipeline overhead" is not so obvious to calculate.
  825.         Look at this:
  826.         add eax,ebx   ; opcode, mod/rm
  827.         add eax,1234h ; opcode, immediate_value
  828.         stosd         ; opcode    <--- these "slow" instruction pipes-in faster
  829.         pop eax       ; opcode    <--- so if you can, put 'em first
  830.  
  831. ------------------
  832. SHORT INSTRUCTIONS
  833. ------------------
  834.  
  835. Short instructions are loaded and decoded faster than longer ones
  836. and since 386 has no internal cache and less memory access bandwidth
  837. than a plain 486, this helps a lot.
  838.  
  839. Well that's all for a 386.
  840.  
  841. -------------------------------------------------------------------------------
  842. CACHE OPTIMIZATION TECHNIQUES  (THEY CAN WORK ON ANY CPU!!!!!!!!!!!!)
  843. -------------------------------------------------------------------------------
  844.  
  845. Usually "code optimization" is cpu-based, but there more things
  846. up in the sky and down on earth than just a cpu... the cache for example!
  847.  
  848. Well, the difference between a cache hit and a cache miss
  849. means lots of cpu cycles lost, so better hit the cached locations to the max.
  850.  
  851. 386 usually have and external 64k ... 128k cache (mine has none, sigh! :( )
  852. 486 have a 4k internal cache and a 64k...512k (usually 256k) second level cache
  853. Pentiums have an Harvard 8k code + 8k data cache
  854. plus a 256k..1Mbyte second level cache.
  855.  
  856. Use "short" loops so there is more probability that the code to execute
  857. will reside fully into the cache.
  858.  
  859. Then remember you can count on an external cache of at least 64k
  860. (usually 128k..256k for a 486).
  861.  
  862. So, if you have to process big arrays or big bitmaps with multiple passages
  863. do not "scan" all the array for every pass, use a "strip by strip"
  864. strategy instead so every "strip" fully fits into the cache
  865. and is ready for the second and third pass without cache misses.
  866.  
  867. This technique is called STRIP-MINING, you can include into your program
  868. a routine that checks the optimal "strip size" trying a multi-pass test
  869. on 64k,128k,256k,512k strips and "complete array"
  870. and then sets the optimal "strip size" to use
  871. when perfoming "strip-mining" routines.
  872.  
  873. On a Pentium you can use 8k "strips" so your "strip mined" routines
  874. will work with the full speed of the internal data cache
  875. (remember the internal cache works at full cpu speed while
  876.  the secondary cache may be runnin at half that).
  877.  
  878. The advantage of strip mining is caused by the fact that
  879. the additional jumping/looping needed to process arrays in "strips"
  880. of adiacent memory locations that can fit together into the cache
  881. is A LOT LESS than the time caused by a single cache miss.
  882.  
  883. -------------------------------------------------------------------------------
  884. NOT SO OBVIOUS OPTIMIZATIONS
  885. -------------------------------------------------------------------------------
  886.  
  887. ----------------------
  888. COMPLEX INSTRUCTIONS
  889. ----------------------
  890. Intel says complex instruction are evil on 486 and up, but there are
  891. exceptions... expecially if want to make things run smooth on 386 too.
  892.  
  893. STRING instructions are FASTER on 386, expecially if they are the first
  894. in a loop.
  895.  
  896. If you have to move data in 32bit chunks you'd better use REP MOVSD if you can
  897. because it alone replaces this "simple instructions only"
  898. super-optimized sequence:
  899.  
  900.         rep_loop:
  901.                 mov eax,[esi]
  902.                 add esi,4      ; or -4
  903.                 mov [edi],eax
  904.                 add edi,4      ; or -4
  905.                 dec ecx
  906.                 jne rep_loop
  907.  
  908. REP MOVSD takes  2+7*n cycles on a 386 or 486
  909.  
  910. While the "optimized" sequence uses EAX
  911. and takes [(2+4+2+2+2+2+7)*n - 4 ] = [21*n - 4] cycles on a 386
  912.       and [  (1+1+1+1+1+3)*n - 2 ] = [ 8*n - 2] cycles on a 486
  913.  
  914. Cache-line aligning the "optimized" code on a Pentium
  915. i think it takes  [ 3*n ]  cycles.
  916. So if 486s are your base system don't throw away REP MOVSD
  917.  
  918. Also remember that REP MOVSD take 2 bytes instead of 13 bytes
  919. does not need to use EAX (one more register free for other things)
  920. and it does not use the Pentium's BTB (Branch Target Buffer)
  921. so you can be sure it does not miss and the outer loops
  922. with entries in the BTB can be one level deeper.
  923.  
  924. What's more, the AMD K5 automatically splits a complex instruction
  925. into an optimized sequence of simple instructions
  926. and issues them to fully utilize the four execution units it has.
  927. Guess what it means for poor old movsd :)
  928.  
  929. <Intel bashing ON>
  930. Heck! I think those Intel engineers lost a big thing when they
  931. decided to not improve MOVS/LODS/STOS. A "blitter" unit directly
  932. controlled by string instructions (with "fetch ahead","bufferize"
  933. and "auto align" capabilities) could be a great thing for us.
  934.  
  935. Think about this: a REP MOVSB/W/D "translated" to
  936. a "head" byte move (to align things)
  937. a "central" qword move (burst read/burst writes)
  938. and a "tail" byte move (to align things).
  939. And all this without trashing the processor data cache!!!!
  940. Can you immagine the boost your code may get?
  941. Heck! Sun engineers ADDED "blitter" support in their new 64bit sparc cpus
  942. because they seen their software moving data a lot, why Intel ones did not?
  943.  
  944. On a Pentium you can get the optimal 2-cycle memory to memory MOV
  945. by way of pipelining, but this cannot take advantage of the fact
  946. that when performing REP MOVS the processor KNOWS AHEAD how many locations
  947. will be moved (read: on a "smarter" cpu this can help optimize to the
  948. max the processor-to-memory bandwidth and avoid caching overhead)
  949. nor it can take advantage of the full power of burst read/writes
  950. neither it can take advantage of the fact that WHILE THE STRING MOVE
  951. IS GOING ON, the processor pipelines can execute OTHER instructions after
  952. the MOVS and "not dealing" with the memory range "under transfert"
  953. or with ECX,ESI,EDI and Direction Flag.
  954. I hope they will take note of this for P7.
  955.  
  956. <Intel bashing OFF>
  957.  
  958. -------------------------------------------------------------
  959. THE ADDRESSING MODE ADVANTAGE
  960. -------------------------------------------------------------
  961. Don't be fooled by the current Riscy trend, be cooler than the rest.
  962. Some Intel "complex addressing" modes are really powerful
  963. if you just have enough creativity.
  964. Lets suppose you need to add together data from "four"
  965. streams of data....
  966.  
  967. A riscy (risc-like) way to do this could be...
  968.                               ; 486 timings when looping
  969.       riscy_way:
  970.                mov eax,[esi]  ; 1
  971.                add esi,4      ; 1
  972.                add eax,[edx]  ; 2
  973.                add edx,4      ; 1
  974.                add eax,[ebx]  ; 2
  975.                add ebx,4      ; 1
  976.                add eax,[ecx]  ; 2
  977.                add ecx,4      ; 1
  978.                mov [edi],eax  ; 1
  979.                add edi,4      ; 1
  980.                dec ebp        ; 1
  981.                jne riscy_way  ; 3
  982.                               ; loop cycles = 17
  983.  
  984. Now lets see the "intelly" way! :)
  985. Let's suppose the "counter" EBP won't exceed 2^31 -1
  986. we can do the following ...
  987.  
  988.                ; move pointers ahead ...
  989.                lea esi,[esi+ebp*4]
  990.                lea edx,[edx+ebp*4]
  991.                lea ebx,[ebx+ebp*4]
  992.                lea ecx,[ecx+ebp*4]
  993.                lea edi,[edi+ebp*4]
  994.                neg ebp ; negate increment
  995.                ; then you can fully use the address unit ALU
  996.  
  997.                                     ; 486 timing when looping
  998.     intelly_way:
  999.                mov eax,[esi+ebp*4]  ; 1
  1000.                add eax,[edx+ebp*4]  ; 2
  1001.                add eax,[ebx+ebp*4]  ; 2
  1002.                add eax,[ecx+ebp*4]  ; 2
  1003.                mov [edi+ebp*4],eax  ; 1
  1004.                inc ebp              ; 1
  1005.                jnz intelly_way      ; 3
  1006.                                     ; loop cycles = 12
  1007.                
  1008.  
  1009. On a Pentium, "riscy" and "intelly" runs at nearly the same speed
  1010. BUT ON A 486, the "riscy" way runs 30% slower than "intelly" !!!!
  1011.  
  1012. This means that using the "riscy" code
  1013. your 486 will look like a slow cow compared to a Pentium
  1014. while using the "intelly" code your 486 will look good enough
  1015. ( not to mention this helps to make the difference between
  1016.   "needs a Pentium" and "this flies on 486 too!!").
  1017.  
  1018. -------------------------------------------------------------
  1019. 32bit ACCESS SPEAKS FOR ITSELF, just remember to fully use it
  1020. -------------------------------------------------------------
  1021.  
  1022. Everywhere you can, use 32bit instructions
  1023. and if you can, align data on 32bit.
  1024.  
  1025. For example, let's say you have to manipulate lots of strings,
  1026. if you align them on dword boundaries (including string lenght)
  1027. with null byte paddings, you can boost processing time MORE THAN 8 TIMES!!!!
  1028.  
  1029. The same thing applies to manipulating 8bit bitmaps and "software" sound mixing.
  1030.  
  1031. Into 386mixer coded a routine that mixed simultaneously 4 sound channels
  1032. running only on internal register and mixing up to 4 samples at a time
  1033. from the 4 channels (look at the "intelly" example above).
  1034.  
  1035. If you need speed, you can even tollerate small calculation errors
  1036. or reduced precision
  1037. and manipulate successive 8,16bit values in a single 32bit instruction.
  1038.  
  1039. Let's say you have and array of unsigned words and you need to multiply them
  1040. for a constant, say 45, how can you do that ?
  1041. If you know the values won't overflow the 16 bit they use
  1042. (if they overflow you will have to choose another method), you can do the
  1043. following:
  1044.            mov ecx,count
  1045.            mov esi,start_address
  1046.      handle_two_words:
  1047.            mov eax,[esi] ; load two words at a time
  1048.            ; an AGI happens, but i can't eliminate it
  1049.            lea eax,[eax+eax*4]  ; multiply by 5
  1050.            add esi,4  ; increment pointer, avoid 486 AGI
  1051.                       ; reduce by 1 the Pentium AGIs
  1052.            lea eax,[eax+eax*8]  ; then multiply by 9
  1053.            dec ecx  ; decrement counter & keep Pentium at full power
  1054.            mov [esi],eax   ;
  1055.            jne handle_two_words
  1056.  
  1057. And if you have very big arrays, you can even unroll two or three times
  1058. the loop to further speed up this code.
  1059.  
  1060. ------------------
  1061. SELF COMPILED CODE
  1062. ------------------
  1063.  
  1064. Sometimes you need to execute lots of times the same "jump filled"
  1065. instruction sequence, and you know ahead what jumps will be taken
  1066. and what won't.
  1067. What's worse if there are lots of conditional jumps (Jcc) "in sequence"
  1068. they may be enough to overflow the capability of branch-prediction units!!!
  1069.  
  1070. So, what can you do?
  1071. My answer to this is a SELF-COMPILER!!!
  1072. A small finite state machine that instead of crunching data directly
  1073. IT GENERATES SUPER-SPECIALIZED ROUTINES that will crunch the data in the
  1074. fastest way the code generator knows.
  1075.  
  1076. I've done a thing like that for the _PageFLip1 routine in 386video.asm.
  1077. At mode initialization a code generator generates
  1078. all the 256 blit-skip sequences the _PageFLip1 routines may need
  1079. when copying "modified" pixels on screen.
  1080.  
  1081. This way a call is performed only after 32 blitted pixels, instead of jumping
  1082. every 2..4 pixels (or every pixels in the worst case situations).
  1083.  
  1084. By the way, this is NOT self-modifying code
  1085. this is an "integrated code compiler".
  1086.  
  1087. ------------------------------------------------------------------------------
  1088. I hope this information has been helpful for you.
  1089. Now make some coffee, brush your teeth and phone up your girlfriend and 
  1090. go and see a movie.   This document will be here when you get back, and I 
  1091. imagine there is only so much of this you can take in one day.... :-)  :-)  :-)
  1092.  
  1093. Live long and code well...
  1094.  
  1095. Regards,
  1096.  
  1097.    Michael Kunstelj.
  1098.  
  1099. Regards from me too,
  1100.  
  1101.    Lorenzo Micheletto
  1102.